/**
 * 文件名称:  TBcRoleServiceImpl.java
 * 文件序号:  序号
 * 内容描述:  BcRoleService接口实现
 * 版权声明:  山东鸿蝶信息技术有限公司
 * 创建用户:  MissJin
 * 创建日期:  2017/1/10
 * 修改用户:  无
 * 修改日期:  无
 * 修改说明:  无
 * 文件版本:
 * 文件路径:
 */
package com.hongdee.rbac.role.service.impl;


import com.hongdee.common.util.TokenUtil;
import com.hongdee.rbac.dept.service.ITBcOrganService;

import com.hongdee.rbac.role.dao.ITBcRoleDao;
import com.hongdee.rbac.role.entity.TBcRole;
import com.hongdee.rbac.role.entity.TBcRoleResource;
import com.hongdee.rbac.role.service.ITBcRoleService;
import com.hongdee.rbac.user.entity.TBcRoleUser;

import jdk.nashorn.internal.parser.Token;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.hongdee.rbac.Constant.RES_ROLE;
import static com.hongdee.rbac.Constant.SUPER_ID;

/**
 * Created by My on 2017/1/10.
 */
@Service
public class TBcRoleServiceImpl implements ITBcRoleService {
    @Autowired
    private ITBcRoleDao bcRoleDao;


    private String tabName = "T_BC_ROLE";
    /*
    *resMap 存储已选中的资源
     */
    private Map<String, String> resMap = null;

    @Autowired
    private ITBcOrganService organService;


    /**
     * 方法名称: page
     * 方法描述: 查询参数
     * 参数名称: Map<String, Object> params 传递的参数
     * 返回内容: ResultEntity 结果集
     * 异常说明:
     * 创建用户:
     * 创建时间:
     * 修改用户:
     * 修改时间:
     * 修改内容:
     */
    @Override
    public Map page(String start, String limit, String uid, String searchValue) throws Exception {
        //获取当前人员所在公司
        String companyId = TokenUtil.getCompanyId(uid);
        //当前人员部门ID
        String deptId = TokenUtil.getDeptId(uid);
        //当前组织的上级
        Map<String, Object> parentMap = this.organService.parentMap(deptId);

        List params = new ArrayList();
        //查询所有角色，公司，是否应用下级部门
        String resSql = "select * from t_bc_role where r_status='1' and id <> '0' ";

        //集团管理员
        if (!"0".equals(companyId)) {
            List<Map<String, Object>> resList = this.bcRoleDao.list(resSql, params.toArray());
            List list = new ArrayList();
            resSql += " and ( id in ( ";
            for (Map resMap : resList) {
                //判断是否应用下级
                switch (resMap.get("hasChild").toString()) {

                    //未应用下级，判断是否为相同的公司ID
                    case "0": {
                        //当前部门与查询已有部门一致
                        if (deptId.equals(resMap.get("oId").toString())) {
                            resSql += " ?, ";
                            params.add(resMap.get("id").toString());
                        }
                    }
                    break;
                    //应用下级，取当前人员所在公司部门向上取值是否与其对应的公司
                    case "1": {

                        /**
                         * 当前组织的上级包含角色对应的组织ID
                         * */
                        //当前角色对应的组织ID
                        String roleOId = resMap.get("oId").toString();
                        if (roleOId.equals(deptId) || parentMap.containsKey(roleOId)) {
                            resSql += " ?, ";
                            params.add(resMap.get("id").toString());
                        }
                    }
                    break;
                }
            }
            resSql += " '' ) or o_id = ? ) ";
            params.add(TokenUtil.getCompanyId(uid));
        }
        if (!searchValue.isEmpty() && searchValue != "") {
            resSql += " and r_name like ? ";
            params.add("%" + searchValue + "%");
        }
        resSql += "  order by r_order asc ";
        return this.bcRoleDao.page(resSql, params.toArray(), start, limit);
    }

    String ORG_PARENT_SQL = " select o_p_id from t_bc_organ where id = ? ";

    private List parent(String oid, List resIds) throws Exception {
        Map temp = this.bcRoleDao.info(ORG_PARENT_SQL, oid);
        if (temp == null || temp.size() == 0) {
            return resIds;
        } else {
            oid = String.valueOf(temp.get("oPId"));
            resIds.add(oid);
            return parent(oid, resIds);
        }
    }

    /**
     * 方法名称: info
     * 方法描述: 根据 ID 查询实体详情
     * 参数名称: String id
     * 返回内容: TBcRole 实例
     * 异常说明:
     * 创建用户:
     * 创建时间:
     * 修改用户:
     * 修改时间:
     * 修改内容:
     */
    @Override
    public Map info(String id) throws Exception {
        if (StringUtils.isEmpty(id)) {
            throw new Exception("请选择角色！");
        }
        String sql = "select * from " + tabName + " where id = ? ";
        return this.bcRoleDao.info(sql, new Object[]{id});
    }

    /**
     * @param id 角色 ID
     * @return 所分配的资源 ID 列表
     * @throws Exception
     * @desc 查询角色对应的资源列表
     */
    @Override
    public List<String> res(String id) throws Exception {
        String sqlStr = "select res_id from t_bc_role_resource where r_id = ?";
        List<Map<String, Object>> resMapList = this.bcRoleDao.list(sqlStr, id);
        List idList = new ArrayList();
        for (Map<String, Object> map : resMapList) {
            idList.add(String.valueOf(map.get("resId")));
        }
        return idList;
    }

    /**
     * 方法名称: update
     * 方法描述: 根据 ID 集合更新角色状态
     * 参数名称: String ids
     * 返回内容: 无
     * 异常说明:
     * 创建用户:
     * 创建时间:
     * 修改用户:
     * 修改时间:
     * 修改内容:
     */
    @Override
    public void update(String ids, String status) throws Exception {
        if (StringUtils.isEmpty(ids)) {
            throw new Exception("请选择角色！");
        } else if (ids.equals("0")) {
            throw new Exception("不允许删除超级管理员角色");
        } else {
            String hql = "update TBcRole t set t.rStatus=:status where t.id = :id ";
            Map params = new HashMap();
            params.put("status", status);
            params.put("id", ids);
            this.bcRoleDao.update(hql, params);
        }
    }

    /**
     * @param data @Service标注的实体
     * @param uid  登录用户 token
     * @return data @Service标注的实体
     * @throws Exception
     * @desc 保存角色
     */
    @Override
    public TBcRole save(TBcRole data, String uid) throws Exception {
        if (null == data.getId()) {
            /**
             * 新增时判断当前用户是否是超管，如果是超管，则将该角色分配给超管，
             * 否则除超管外，还需分配给当前创建用户
             */
            this.bcRoleDao.saveOrUpdate(data);
            List<Object> ls = new ArrayList();

            //保存关联关系
            TBcRoleUser tr = new TBcRoleUser();
            tr.setId(null);
            tr.setrId(data.getId());
            tr.setuId(SUPER_ID);
            tr.setType(RES_ROLE);
            ls.add(tr);
            if (!SUPER_ID.equals(uid)) {
                TBcRoleUser tu = new TBcRoleUser();
                tu.setrId(data.getId());
                tu.setuId(uid);
                tu.setType(RES_ROLE);
                tu.setId(null);
                ls.add(tu);
            }
            this.bcRoleDao.saveOrUpdateList(ls);
        } else {
            //编辑
            this.bcRoleDao.saveOrUpdate(data);
        }
        return data;

    }


    /***
     *
     * @param id 角色主键
     * @param resIds 分配的资源主键数据
     * @throws Exception
     */
    @Override
    public void saveRes(String id, String[] resIds) throws Exception {
        // 先删除
        // 后保存
        String delHQL = " delete from TBcRoleResource where rId = :id ";
        Map<String, Object> params = new HashMap();
        params.put("id", id);
        this.bcRoleDao.update(delHQL, params);
        List entityList = new ArrayList();
        TBcRoleResource roleResource;
        for (String resId : resIds) {
            roleResource = new TBcRoleResource();
            roleResource.setResId(resId);
            roleResource.setrId(id);
            entityList.add(roleResource);
        }
        this.bcRoleDao.saveOrUpdateList(entityList);
    }

    /**
     * @param uid 异常
     * @return 角色列表
     * @throws Exception 基类异常
     * @desc 根据当前登录用户查询其可进行分配的角色
     * @author zhangkai
     * @date 2017/2/11
     * @time 09:37
     * @update_user
     * @update_time
     * @update_desc:
     */
//    @Override
//    public List tree(String uid, String type) throws Exception {
//        //当前管理员，只可分配，其拥有的访问角色权限
//        String sqlStr = " select DISTINCT r.id,r.r_name,ru.r_type from t_bc_role r , t_bc_role_user ru " +
//                " where r.r_status='1'  and r.id= ru.r_id and ru.r_type='0' and ru.u_id= ? ";
//        return this.bcRoleDao.list(sqlStr, uid);
//    }
    @Override
    public List tree(String uid, String type) throws Exception {
        //当前管理员，只可分配，其拥有的访问角色权限
        String sqlStr = " select DISTINCT r.id,r.r_name,ru.r_type from t_bc_role r , t_bc_role_user ru " +
                " where r.r_status='1'  and r.id= ru.r_id and ru.r_type='0' and ru.u_id= ? ";
        Map map = this.page("0", "65536", uid, "");
        List data = (List) map.get("dataList");
        List datasqlStr = this.bcRoleDao.list(sqlStr, uid);
        return data;
    }

    /**
     * @param rId 角色 ID
     * @return 角色列表
     * @throws Exception 基类异常
     * @desc 根据当前登录用户查询其可进行分配的角色
     * @author zhangkai
     * @date 2017/2/11
     * @time 09:37
     * @update_user
     * @update_time
     * @update_desc:
     */
    @Override
    public List checkedResTree(String rId) throws Exception {
        //获取角色对应的资源
        resMap = getCheckResMap(rId);
        return buildResChild("0");
    }

    /**
     * @param pId 上级资源 ID
     * @return List
     * @throws Exception
     * @desc 拼接选择的资源树
     */
    private List buildResChild(String pId) throws Exception {
        if (null == pId || org.springframework.util.StringUtils.isEmpty(pId)) {
            pId = "0";
        }
        String sqlStr = "select * from t_bc_resource where res_p_id = ? order by res_order asc";
        List<Map<String, Object>> treeP = this.bcRoleDao.list(sqlStr, pId);
        return buildResParent(treeP);
    }

    /**
     * @param treeP 节点列表
     * @return
     * @throws Exception 基类
     * @desc 获取当前节点的子节点，并生成树状结点，结合buildResChild使用
     */
    private List buildResParent(List<Map<String, Object>> treeP) throws Exception {
        if (treeP.size() == 0) {
            return treeP;
        }
        List<Map<String, Object>> treeList = new ArrayList<>();
        List<Map<String, Object>> childList;
        for (Map map : treeP) {
            String resId = String.valueOf(map.get("id"));
            childList = buildResChild(resId);
            if (childList.size() == 0) {
                //不存在子节点时，判断当前节点是为选中节点
                if (resMap.containsKey(resId)) {
                    treeList.add(map);
                }
                continue;
            }
            //存在子节点，增加子节点 返回
            map.put("child", childList);
            treeList.add(map);
        }
        return treeList;
    }


    /**
     * @param rId
     * @return Map
     * @throws Exception
     * @desc 获取当前角色 已分配的资源列表
     */
    private Map<String, String> getCheckResMap(String rId) throws Exception {
        String sqlStr = " select res_id,r_id  from t_bc_role_resource where r_id = ? ";
        List<Map<String, Object>> resList = this.bcRoleDao.list(sqlStr, rId);
        Map<String, String> tempMap = new HashMap();
        for (Map map : resList) {
            //资源 ID 当做主键
            tempMap.put(String.valueOf(map.get("resId")), rId);
        }
        return tempMap;
    }

    /**
     * @param
     * @return Map
     * @throws Exception
     * @desc 角色转换
     * @author 徐钦勇
     */
    @Override
    public Map convert() throws Exception {
        String sql = " select * from " + tabName + "  ";
        List<Map<String, Object>> mapList = this.bcRoleDao.list(sql);
        Map temp = new HashMap();
        for (Map map : mapList) {
            temp.put(map.get("id"), map.get("rName"));
        }
        return temp;
    }

    @Override
    public void startAndStopRole(String uid, String roleId, String status) throws Exception {
        boolean flag = this.checkCompanyInfo(uid, roleId);
        if (flag) {
            //可以继续执行
            this.update(roleId, status);
        } else {
            Map<String, String> map = TokenUtil.getCompany(uid);
            //不在当前公司下 不允许继续执行
            throw new Exception("该角色不隶属" + map.get("oName") + "，暂无权限操作！！");
        }

    }

    /**
     * 根据当前登录用户ID及要处理操作的角色ID
     * 判定该角色是否在该公司下
     *
     * @param uid
     * @param roleId
     * @return true在公司下 false 不在该公司下不允许停用、启用、编辑
     * @throws Exception
     */
    @Override
    public boolean checkCompanyInfo(String uid, String roleId) throws Exception {
        //获得角色详情
        Map<String, Object> role = this.bcRoleDao.info(tabName, "id", roleId);
        //取出所属部门信息
        String oId = String.valueOf(role.get("oId"));
        boolean flag = false;
        //取出当前登录用户所在的公司信息
        String companyId = TokenUtil.getCompanyId(uid);
        //取得公司下所有部门信息
        List<String> deptList = new ArrayList<>();
        deptList.add(companyId);
        buildDeptChild(companyId, deptList);
        if (deptList.contains(oId)) {
            flag = true;
        }
        return flag;
    }

    //伪递归查询公司下所有部门

    @Override
    public List<Map<String, Object>> buildDeptChild(String opId, List<String> deptList) throws Exception {
        String sqlStr = "select * from t_bc_organ  where o_p_id = ? ";
        List<Map<String, Object>> child = this.bcRoleDao.list(sqlStr, opId);
        return buildDeptParent(child, deptList);
    }

    public List<Map<String, Object>> buildDeptParent(List<Map<String, Object>> paranet, List<String> deptList) throws Exception {
        if (paranet.size() == 0) {
            return paranet;
        }
        String pId;
        for (Map<String, Object> temp : paranet) {
            pId = String.valueOf(temp.get("id"));
            List<Map<String, Object>> childList = buildDeptChild(pId, deptList);
            temp.put("child", childList);
            deptList.add(pId);
        }
        return paranet;
    }


    @Override
    public List<Map<String, Object>> getRoleDateByUid(String uid) throws Exception {
        String sql = "select * from t_bc_role where id in ( select r_id from t_bc_role_user where r_type='0' and u_id=? )";
        return this.bcRoleDao.list(sql, uid);
    }


    /**
     * @return
     * @throws Exception
     * @desc 角色下拉
     * @author 于扬
     */
    @Override
    public List<Map> combo(String oid) throws Exception {
        //查询已启用的角色
        String sql = " select * from " + tabName + " where o_id =? and r_status = '1'";
        List params = new ArrayList();
        if (!StringUtils.isEmpty(oid)) {
            params.add(oid);
        }
        System.out.println(sql);
        List<Map<String, Object>> mapList = this.bcRoleDao.list(sql, oid);
        List<Map> resList = new ArrayList<Map>();
        Map temp;
        for (Map map : mapList) {
            temp = new HashMap();
            temp.put("label", map.get("rName"));
            temp.put("value", map.get("id"));
            resList.add(temp);
        }
        System.out.println(resList.toString());
        return resList;
    }

    /**
     * @return
     * @throws Exception
     * @desc 角色转换
     * @author 于扬
     */
    @Override
    public Map<String, String> scmconvert(String oid) throws Exception {
        String sql = " select * from " + tabName;
        /*List params = new ArrayList();
        if (!StringUtils.isEmpty(oid)) {
            params.add(oid);
        }*/
        List<Map<String, Object>> mapList = this.bcRoleDao.list(sql);
        List<Map> resList = new ArrayList<Map>();
        Map temp = new HashMap();
        for (Map map : mapList) {
            temp.put(map.get("id"), map.get("rName"));
        }
        return temp;
    }

}
